#include "compiler.h"
#include "../stdafx.h"
#include "../Memory/strings.h"
using namespace XScript::Memory::Strings;
namespace XScript::Compile
{
	FunctionDefinition CompilerTag::SearchFunction(RawString name)
	{
		Compiler compiler = this;
		assert(function_list != nullptr);
		auto result = find_if(compiler->function_list->begin(), compiler->function_list->end(), [name](auto x) -> bool {
			return RawStringCompare(name, x->name);
		});
		if (result != compiler->function_list->end())
		{
			return *result;
		}
		return nullptr;
	}

	Declaration CompilerTag::SearchDeclaration(RawString identifier, Block block)
	{
		assert(declaration_list != nullptr);
		for (auto b_pos = block; b_pos; b_pos = b_pos->outer_block)
		{
			for (auto d_pos = b_pos->declaration_list->begin(); d_pos != b_pos->declaration_list->end(); d_pos++)
			{
				if (RawStringCompare(identifier, (*d_pos)->name))
				{
					return *d_pos;
				}
			}
		}
		assert(declaration_list != nullptr);
		Compiler compiler = this;
		for (auto d_pos = compiler->declaration_list->begin(); d_pos != compiler->declaration_list->end(); d_pos++)
		{
			if (RawStringCompare(identifier, (*d_pos)->name))
			{
				return *d_pos;
			}
		}
		return nullptr;
	}

	void CompilerTag::AppendFunction(FunctionDefinition fd)
	{
		assert(function_list != nullptr);
		function_list->push_back(fd);
	}

	void CompilerTag::Compile()
	{

	}

	void CompilerTag::FixAst()
	{


	}

	Compiler xscriptcall CompilerTag::GetCurrent()
	{
		return GetStaticCompilerRef();
	}

	Compiler xscriptcall CompilerTag::Create(FILE * fp)
	{
		BlockMemoryManager*block = new BlockMemoryManager();
		Compiler com = block->NewPointer<CompilerTag>(block, fp);
		return com;
	}

	void xscriptcall CompilerTag::Dispose(Compiler compiler)
	{
		delete GetStaticCompilerRef();
		GetStaticCompilerRef() = nullptr;
	}

	void CompilerTag::DoCompile()
	{
		if (yyparse())
		{
			cerr << "Error ! Error ! Error !" << endl;
			exit(1);
		}
	}

	CompilerTag::CompilerTag(BlockMemoryManager * memory, FILE * fp)
	{
		yyin = fp;
		setlocale(LC_ALL, "chs");
		this->current_memory = memory;
		string_pool = memory->NewPointer<RawStringManager>();
		function_list = memory->NewPointer<list<FunctionDefinition>>();
		declaration_list = memory->NewPointer<list<Declaration>>();
		statement_list = memory->NewPointer<list<Statement>>();
		current_block = nullptr;
		this->current_line_number = 1;
	}

	Compiler &xscriptcall CompilerTag::GetStaticCompilerRef()
	{
		static Compiler compiler = nullptr;
		return compiler;
	}

}